﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Assembly.Metro.Controls.PageTemplates.Games.Components.MetaData
{
    /// <summary>
    /// Base class for number data.
    /// </summary>
    /// <typeparam name="T">The type of number to hold.</typeparam>
    public abstract class NumberData<T> : ValueField
    {
        private string _type;
        private T _value, _originalValue;

        public NumberData(string name, uint offset, string type, T value, uint pluginLine)
            : base(name, offset, pluginLine)
        {
            _type = type;
            _value = value;
            _originalValue = value;
        }

        public string Type
        {
            get { return _type; }
            set { _type = value; NotifyPropertyChanged("Type"); }
        }

        public T Value
        {
            get { return _value; }
            set { _value = value; NotifyPropertyChanged("Value"); }
        }

        public override bool HasChanged
        {
            get { return !_value.Equals(_originalValue); }
        }

        public override void Reset()
        {
            Value = _originalValue;
        }

        public override void KeepChanges()
        {
            _originalValue = _value;
        }

        protected MetaField CloneBase(NumberData<T> data)
        {
            data._originalValue = _originalValue;
            return data;
        }
    }

    /// <summary>
    /// Unsigned byte.
    /// </summary>
    public class Uint8Data : NumberData<byte>
    {
        public Uint8Data(string name, uint offset, string type, byte value, uint pluginLine)
            : base(name, offset, type, value, pluginLine) { }

        public override void Accept(IMetaFieldVisitor visitor)
        {
            visitor.VisitUint8(this);
        }

        public override MetaField DeepClone()
        {
            return CloneBase(new Uint8Data(Name, Offset, Type, Value, base.PluginLine));
        }
    }

    /// <summary>
    /// Signed byte.
    /// </summary>
    public class Int8Data : NumberData<sbyte>
    {
        public Int8Data(string name, uint offset, string type, sbyte value, uint pluginLine)
            : base(name, offset, type, value, pluginLine) { }

        public override void Accept(IMetaFieldVisitor visitor)
        {
            visitor.VisitInt8(this);
        }

        public override MetaField DeepClone()
        {
            return CloneBase(new Int8Data(Name, Offset, Type, Value, base.PluginLine));
        }
    }

    /// <summary>
    /// Unsigned 16-bit integer.
    /// </summary>
    public class Uint16Data : NumberData<ushort>
    {
        public Uint16Data(string name, uint offset, string type, ushort value, uint pluginLine)
            : base(name, offset, type, value, pluginLine) { }

        public override void Accept(IMetaFieldVisitor visitor)
        {
            visitor.VisitUint16(this);
        }

        public override MetaField DeepClone()
        {
            return CloneBase(new Uint16Data(Name, Offset, Type, Value, base.PluginLine));
        }
    }

    /// <summary>
    /// Signed 16-bit integer.
    /// </summary>
    public class Int16Data : NumberData<short>
    {
        public Int16Data(string name, uint offset, string type, short value, uint pluginLine)
            : base(name, offset, type, value, pluginLine) { }

        public override void Accept(IMetaFieldVisitor visitor)
        {
            visitor.VisitInt16(this);
        }

        public override MetaField DeepClone()
        {
            return CloneBase(new Int16Data(Name, Offset, Type, Value, base.PluginLine));
        }
    }

    /// <summary>
    /// Unsigned 32-bit integer.
    /// </summary>
    public class Uint32Data : NumberData<uint>
    {
        public Uint32Data(string name, uint offset, string type, uint value, uint pluginLine)
            : base(name, offset, type, value, pluginLine) { }

        public override void Accept(IMetaFieldVisitor visitor)
        {
            visitor.VisitUint32(this);
        }

        public override MetaField DeepClone()
        {
            return CloneBase(new Uint32Data(Name, Offset, Type, Value, base.PluginLine));
        }
    }

    /// <summary>
    /// Signed 32-bit integer.
    /// </summary>
    public class Int32Data : NumberData<int>
    {
        public Int32Data(string name, uint offset, string type, int value, uint pluginLine)
            : base(name, offset, type, value, pluginLine) { }

        public override void Accept(IMetaFieldVisitor visitor)
        {
            visitor.VisitInt32(this);
        }

        public override MetaField DeepClone()
        {
            return CloneBase(new Int32Data(Name, Offset, Type, Value, base.PluginLine));
        }
    }

    /// <summary>
    /// 32-bit floating-point number.
    /// </summary>
    public class Float32Data : NumberData<float>
    {
        public Float32Data(string name, uint offset, string type, float value, uint pluginLine)
            : base(name, offset, type, value, pluginLine) { }

        public override void Accept(IMetaFieldVisitor visitor)
        {
            visitor.VisitFloat32(this);
        }

        public override MetaField DeepClone()
        {
            return CloneBase(new Float32Data(Name, Offset, Type, Value, base.PluginLine));
        }
    }
}
